void generatePoses(){
//  debugCounter++;
  myParticle[0] = new Particle(new Vector3d(0.0 ,0.0 ,0.0),  myMass, myRadius, new Vector3d(100,100,100));
  myParticle[1] = new Particle(new Vector3d(myLegLength,0.0 ,0.0), myColorMass, myColorRadius, new Vector3d(255,  0,  0));
  myParticle[2] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0),myLegLength*sin(2.0*PI/3.0),0.0), myColorMass, myColorRadius, new Vector3d(0  ,255,  0));
  myParticle[3] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0),myLegLength*sin(4.0*PI/3.0),0.0), myColorMass, myColorRadius, new Vector3d(0  ,0  ,255));
  myParticle[4] = new Particle(new Vector3d(myLegLength/3,0.0,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[5] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0)/3,myLegLength*sin(2.0*PI/3.0)/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[6] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0)/3,myLegLength*sin(4.0*PI/3.0)/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[7] = new Particle(new Vector3d(myLegLength*2.0/3,0.0,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[8] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0)*2.0/3,myLegLength*sin(2.0*PI/3.0)*2.0/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[9] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0)*2.0/3,myLegLength*sin(4.0*PI/3.0)*2.0/3,0.0), myMass, myRadius, new Vector3d(100,100,100));

  for (int i=0; i<10; i++){
    myParticle[i].alphaValue = 255.0;
  }

  myPose = new Pose(myParticle, myPlayer);//Clear
}


void resetPose(boolean isR, boolean isG, boolean isB){
//  println("Reset at "+stepCount);
//      debugCounter++;
  float alphaFactor = curlSens*Math.abs(smoothedAngularVelocity) / (curlThresh + Math.abs(smoothedAngularVelocity)*curlSens);
  float angleRotation = -(2*PI / 9.0) * alphaFactor * smoothedAngularVelocity/(Math.abs(smoothedAngularVelocity)+.0001);
  
  myParticle[0] = new Particle(new Vector3d(0.0 ,0.0 ,0.0),  myMass, myRadius, new Vector3d(100,100,100));
  float defaultLegLength = myLegLength;
  if (isR){
    myLegLength *= legExtendFactor;
  }
  myParticle[1] = new Particle(new Vector3d(myLegLength,0.0 ,0.0), myMass, myRadius, new Vector3d(255,  0,  0));
  myParticle[4] = new Particle(new Vector3d(myLegLength/3,0.0,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[7] = new Particle(new Vector3d(myLegLength*2.0/3,0.0,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myLegLength = defaultLegLength;
  if (isG){
    myLegLength *= legExtendFactor;
  }
  myParticle[2] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0),myLegLength*sin(2.0*PI/3.0),0.0), myMass, myRadius, new Vector3d(0  ,255,  0));
  myParticle[5] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0)/3,myLegLength*sin(2.0*PI/3.0)/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[8] = new Particle(new Vector3d(myLegLength*cos(2.0*PI/3.0)*2.0/3,myLegLength*sin(2.0*PI/3.0)*2.0/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myLegLength = defaultLegLength;
  if (isB){
    myLegLength *= legExtendFactor;
  }
  myParticle[3] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0),myLegLength*sin(4.0*PI/3.0),0.0), myMass, myRadius, new Vector3d(0  ,0  ,255));
  myParticle[6] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0)/3,myLegLength*sin(4.0*PI/3.0)/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myParticle[9] = new Particle(new Vector3d(myLegLength*cos(4.0*PI/3.0)*2.0/3,myLegLength*sin(4.0*PI/3.0)*2.0/3,0.0), myMass, myRadius, new Vector3d(100,100,100));
  myLegLength = defaultLegLength;

  if (invertedRGB) { angleRotation *= -1.0; }
 
  rotate2d(myParticle[4].position,angleRotation*2);
  rotate2d(myParticle[7].position,angleRotation);
  rotate2d(myParticle[5].position,angleRotation*2);
  rotate2d(myParticle[8].position,angleRotation);
  rotate2d(myParticle[6].position,angleRotation*2);
  rotate2d(myParticle[9].position,angleRotation);
  /*float norm1 = myParticle[1].position.norm();
  float norm2 = myParticle[2].position.norm();
  float norm3 = myParticle[3].position.norm();
  myParticle[4].position.multiply( ((norm1*.6666 + norm2*.3333)*alphaFactor + myParticle[4].position.norm()*(1.0-alphaFactor))/myParticle[4].position.norm() );
  myParticle[7].position.multiply( ((norm1*.3333 + norm2*.6666)*alphaFactor + myParticle[7].position.norm()*(1.0-alphaFactor))/myParticle[7].position.norm() );
  myParticle[5].position.multiply( ((norm2*.6666 + norm3*.3333)*alphaFactor + myParticle[5].position.norm()*(1.0-alphaFactor))/myParticle[5].position.norm() );
  myParticle[8].position.multiply( ((norm2*.3333 + norm3*.6666)*alphaFactor + myParticle[8].position.norm()*(1.0-alphaFactor))/myParticle[8].position.norm() );
  myParticle[6].position.multiply( ((norm3*.6666 + norm1*.3333)*alphaFactor + myParticle[6].position.norm()*(1.0-alphaFactor))/myParticle[6].position.norm() );
  myParticle[9].position.multiply( ((norm3*.3333 + norm1*.6666)*alphaFactor + myParticle[9].position.norm()*(1.0-alphaFactor))/myParticle[9].position.norm() );
  */

  myPose = new Pose(myParticle, myPlayer);
  myPlayer.setPose(myPose);
}  

// Player and Pose classes

class Pose{
  private Vector3d rawPosition[];
  public float targetSpring[];
  private Player player;

  private int numParticles;
  public Pose(Vector3d _rawPosition[], Player _player){
    rawPosition = new Vector3d[_rawPosition.length];
    for (int i=0; i<_rawPosition.length; i++){
      rawPosition[i] = new Vector3d(_rawPosition[i]);
    }
    player = _player;
    numParticles = rawPosition.length;
    targetSpring = new float[(numParticles*(numParticles-1)/2)];
    getSpringLengths();
  }

  public Pose(Particle[] _p, Player _player){
    this(particlesToVectors(_p),_player);
  }

  private void getSpringLengths(){
    for (int i=0; i<numParticles-1; i++){
      for (int j=i+1; j<numParticles; j++){
        targetSpring[getSpringIndex(i,j)] = rawPosition[i].distanceTo(rawPosition[j]);
      }
    }
  }
  private int getSpringIndex(int _i, int _j){
    int result = 0;
    for (int i=0; i<_i; i++){
      result += numParticles -2 - i;
    }
    result += _j - 1;
    return result;
  }
}//end Pose class

class Player{
  private Spring springList[];
  private Particle particle[];
  private int numParticles;
  private Pose pose;
  private float springLengthEasing;
  private float springStrength;
  private float springDamping;
  public boolean drawn;
  public boolean simulating;


  {
    springLengthEasing = 60; //speed of easing
    springStrength = springConstant;
    springDamping = 24.9;
    drawn = true;
    simulating = true;
  }
  
  public void setSpringStrength(float s){
    springStrength = s;
    for (int i=0; i<springList.length; i++){
      springList[i].setForceConstant(s);
    }
  }

  public Player(Particle[] myParts){
    particle = new Particle[myParts.length];
    for (int i=0; i<myParts.length; i++){
      particle[i] = new Particle(myParts[i]);
      
      particle[i].setPlayer(true);
    }
    numParticles = myParts.length;
    springList = new Spring[numParticles*(numParticles-1)/2];
    pose = new Pose(particlesToVectors(myParts), this);
    initSpringLengths();
  }

  public void draw(){
    if (!drawn) return;
    for (int i=0; i<numParticles; i++){
      particle[i].draw();
    }
  }
  
  public void draw(float myAlpha){
    if (!drawn) return;
    for (int i=0; i<numParticles; i++){
      particle[i].draw(myAlpha);
    }
  }

  private void handleKeys(){
  }

  public void setPose(Pose _pose){
    pose = _pose;
  }

  public Pose getPose(){
    return pose;
  }

  public void translate(Vector3d moveMe){
    for(int i=0; i<numParticles; i++){
      particle[i].position.add(moveMe);
      particle[i].positionLast.add(moveMe);
    }
  }
  
  public void rotate(float rotBy){
    float cosTheta = cos(rotBy);
    float sinTheta = sin(rotBy);
    for (int i=0; i<numParticles; i++){
      Vector3d pos = particle[i].position;
      particle[i].position = new Vector3d( pos.x*cosTheta + pos.y*sinTheta, pos.x*sinTheta - pos.y*cosTheta, 0.0 );
      particle[i].positionLast = new Vector3d(pos.x*cosTheta + pos.y*sinTheta, pos.x*sinTheta - pos.y*cosTheta, 0.0 );
    }
  }
  
  public void scale(float factor){
    for (int i=0; i<numParticles; i++){
      particle[i].position = particle[i].position.times(factor);
      particle[i].positionLast = particle[i].positionLast.times(factor);
    }
  }
  
  public void addForce(Vector3d fAdd, int index){
    particle[index].forceAdd(fAdd);
  }

  public Particle getParticle(int index){
    return particle[index];
  }

  public void timeStep(float tstep){
    if (!simulating) return;
    handleKeys();
    easeSpringLengths(tstep);
    for (int i=0; i<springList.length; i++){
      springList[i].applyForce();
    }
    for (int i=0; i<particle.length; i++){
      particle[i].timeStep(tstep);
    }
  }

  private void initSpringLengths(){
    for (int i=0; i<numParticles-1; i++){
      for (int j=i+1; j<numParticles; j++){
        int k = getSpringIndex(i,j);
        springList[k] = new Spring(particle[i],particle[j],pose.targetSpring[k],springStrength, springDamping);
      }
    }
  }

  private void easeSpringLengths(float tstep){
    for (int i=0; i<numParticles-1; i++){
      for (int j=i+1; j<numParticles; j++){
        int k = getSpringIndex(i,j);
        springList[k].setRestLength( springList[k].getRestLength() * (1.0 - tstep*springLengthEasing) + (tstep*springLengthEasing)*pose.targetSpring[k] );
      }
    }
  }

  private int getSpringIndex(int _i, int _j){
    int result = 0;
    for (int i=0; i<_i; i++){
      result += numParticles -2 - i;
    }
    result += _j - 1;
    return result;
  }

  public void constrainBox(Vector3d minV, Vector3d maxV){
    for (int i=0; i<numParticles; i++){
      particle[i].constrainBox(minV, maxV);
    }
  }

}
